home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
strategy
/
xnetbris.00
/
xnetbris
/
client.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-07-23
|
9KB
|
346 lines
/*
This is the network back-end for Netbrisk (the client program).
Copyright (C) 1995 Brendan Bartlett
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* The "protocol" for the server is as follows -
* - a packet of type INFORM_TYPE telling the client the numplayers and play_type
* - a MOVE_TYPE packet, with the brisk card in the card.
*
* - 3 MOVE_TYPE packets, giving the client the cards in their hand
*
* after the beginning point, the game is fairly normal with
* - packets of MOVE_TYPE or MESSAGE_TYPE
* - a very important packets of MOVE_EXPECTED tells the client that
* a move is expected from them now, and the server is idling.
*
*
* the client can do whatever they want with these packets
* "Fabio" and Brendan Bartlett, 1995
*/
/* Arggg!
* For the servers convience, the graphics are a little screwed up
* the card->weight:
* 9 ace
* 8 three
* 7 king (re)
* 6 girl (donna)
* .
* .
* .
*/
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/uio.h>
#include "brisk.h"
int server_fd, numplayers, play_type, okmove, my_number;
char *errormsg;
static struct card brisk;
static struct card hand[3]; /* This is an array with the current cards in this players hand */
void process_input(void);
extern void show_brisk(int, int); /* calls from here to front end */
extern void show_card(int, int, int);
extern void show_table(int, int, int); /* " " */
extern void show_clear_table(char, char, int);
extern void show_move_expected(int);
void open_server(char *, int);
int play_card(int); /* called from front-end */
void ok_score(void);
static int get_card(int); /* reads a new card from the server */
static int give_score(int, char *);
static void update_cards(void); /* some sort of change to the hand -- tell the user */
int handler(int signum);
int start_client(char * hostname, int port);
int handler(int signum)
{
fprintf(stderr, "got SIGPIPE, client cleaning..\n");
close(server_fd);
exit(0);
}
/* Tries to connect with the server given by 'hostn'
*/
void open_server(char *hostn, int dport)
{
int port = 10000;
struct packet p;
int i;
signal(SIGPIPE, handler);
if(dport != 0)
port = dport;
if(!start_client(hostn, port))
{
printf("cannot connect to server '%s'\n", hostn);
exit(0);
}
/* Read in our hand from the server */
for(i = 0; i < 3; i++)
{
get_card(i);
show_card(i, hand[i].suit, hand[i].weight);
}
/* Read in the brisk from the server */
read(server_fd, &p, sizeof(struct packet));
if(p.type != MOVE_TYPE || p.data.move.player != 5)
{
fprintf(stderr, "server did not send the brisk card!\n");
exit(0);
}
memcpy(&brisk, &p.data.move.play_card, sizeof(struct card));
show_brisk(brisk.suit, brisk.weight);
}
/*
* This routine will read from the server for a packet of MOVE_TYPE (or DEAL_TYPE) and will fill in the
* given card in the hand[] array.
*
* If the packet is of type DEAL_TYPE, the argument 'card' is ignored and the suggested value in the
* packet is used instead.
*
* Returns 0 on failure
* 1 on success
*/
static int get_card(int card)
{
struct packet p;
read(server_fd, &p, sizeof(struct packet));
if( (p.type != MOVE_TYPE) && (p.type != DEAL_TYPE) )
{
fprintf(stderr, "FATAL ERROR: MOVE_TYPE or DEAL_TYPE expected!\n");
return 0;
}
if(p.type == DEAL_TYPE)
memcpy(&hand[p.data.deal.rec_place], &p.data.deal.deal_card, sizeof(struct card));
else
memcpy(&hand[card], &p.data.move.play_card, sizeof(struct card));
return 1;
}
void ok_score(void)
{
struct packet out;
out.type = OK;
write(server_fd, &out, sizeof(struct packet));
}
void process_input(void)
{
struct packet in, out;
char buf[80];
int i;
read(server_fd, &in, sizeof(struct packet));
switch(in.type)
{
case LAST_HAND:
show_brisk(-1, -1); /* tell the front-end to erase the brisk card */
break;
case END_GAME:
printf("That's the end of the game!\n");
printf("Final Scores: %d for you, %d for the other %s\n",
give_score(0, in.data.score.scores),
give_score(1, in.data.score.scores), (play_type == CHAOS) ? "player" : "team");
close(server_fd);
exit(0);
case MESSAGE_TYPE:
printf("message: [%s]\n", in.data.message.string);
break;
case MOVE_TYPE:
show_table(in.data.move.tablepos, in.data.move.play_card.suit, in.data.move.play_card.weight);
break;
case SCORE_UPDATE:
show_clear_table(give_score(0, in.data.score.scores),
give_score(1, in.data.score.scores), in.data.score.lastwin);
break;
case DEAL_TYPE:
memcpy(&hand[in.data.deal.rec_place], &in.data.deal.deal_card, sizeof(struct card));
show_card(in.data.deal.rec_place, hand[in.data.deal.rec_place].suit, hand[in.data.deal.rec_place].weight);
break;
case INFORM_TYPE:
printf("server send INFORM_TYPE. Not at start of game\n");
break;
case MOVE_EXPECTED:
if(in.data.move.player == my_number)
okmove = 1;
show_move_expected(in.data.move.player);
}
}
/*
* Given the packet 'p' return the score of 'who', where
* who is 0 for yourself and 1 for the other player/team
*/
static int give_score(int who, char *scores)
{
char scoretab[] = { 0, 1, 0, 1 };
if(who == 0)
return scores[scoretab[my_number]];
else
return scores[! scoretab[my_number]];
}
int play_card(int cardnum)
{
struct packet out, in;
if(!okmove)
{
errormsg = "It's not your turn!";
return 0;
}
if(hand[cardnum].suit == -1 && hand[cardnum].weight == -1)
{
errormsg = "There's no card there!";
return 0;
}
out.type = MOVE_TYPE;
out.data.move.player = my_number;
out.data.move.play_card.suit = hand[cardnum].suit;
out.data.move.play_card.weight = hand[cardnum].weight;
write(server_fd, &out, sizeof(struct packet));
read(server_fd, &in, sizeof(struct packet));
if(in.type != OK)
{
printf("Impossible: not OK in play_card [num %d]: %d %d\n", cardnum, hand[cardnum].suit, hand[cardnum].weight);
return 0;
}
hand[in.data.ok.cardpos].suit = -1;
hand[in.data.ok.cardpos].weight = -1;
okmove = 0;
return 1;
}
int start_client(char *hostname, int port)
{
struct sockaddr_in addr;
struct protoent *proto;
struct hostent *host;
struct packet p;
proto = getprotobyname("tcp");
if(!proto)
{
printf("tcp not supported here.\n");
return 0;
}
host = gethostbyname(hostname);
if(!host)
{
printf("cannot find host '%s'\n", host);
return 0;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(hostname);
memcpy((char *)&addr.sin_addr, (char *)(*host->h_addr_list), host->h_length);
server_fd = socket(PF_INET, SOCK_STREAM, proto->p_proto);
if(server_fd == -1)
{
perror("socket");
return 0;
}
printf("Attemping to connect to port %i of server %s.\n", port, hostname);
if(connect(server_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
{
perror("connect");
return 0;
}
read(server_fd, &p, sizeof(struct packet));
printf("# players %d, play_type %d. I am player # %d\n", p.data.inform.numplayers, p.data.inform.play_type,
p.data.inform.yournumber);
numplayers = p.data.inform.numplayers;
play_type = p.data.inform.play_type;
my_number = p.data.inform.yournumber;
return 1;
}